﻿/*----------------------------------------------------------------
 * 
 * 
 * Hikvision SDK
 * 
 * 2019-7-29 
 * 
 * daniel.zhang
 * 
 * 文件名：CardManage.cs
 * 
 * 文件功能描述：设备管理服务调用封装类
 * 
 * 修改记录：
 * 
----------------------------------------------------------------*/

using System;
using System.Runtime.ExceptionServices;
using System.Runtime.InteropServices;
using Com.Hikvision.Wrapper.Core;
using Com.Hikvision.Wrapper.EntranceControl.RemoteEntranceControl;

namespace Com.Hikvision.Wrapper.Service.EntranceControl.RemoteEntranceControl
{
    /// <summary>
    /// 卡片管理服务调用封装类
    /// </summary>
    public class DeviceManage
    {
        private static readonly Core.Infrastructure coreInfrastructure = new Infrastructure();
        private static readonly LoginManage loginManage = new LoginManage();


        /// <summary>
        /// 获取设备时间
        /// </summary>
        /// <param name="errorCode"></param>
        /// <param name="message"></param>
        /// <param name="deviceIp"></param>
        /// <param name="devicePort"></param>
        /// <param name="userName"></param>
        /// <param name="password"></param>
        /// <returns></returns>
        [HandleProcessCorruptedStateExceptions]
        public DateTime? TimeGet(
            out int errorCode,
            out string message,
            string deviceIp,
            int devicePort,
            string userName = "admin",
            string password = "")
        {
            message = string.Empty;
            errorCode = -100;

            try
            {
                //初始化
                coreInfrastructure.NetDvrInit();

                //登录
                var iUserId = loginManage.LoginDevice(deviceIp, devicePort, userName, password, out errorCode);

                if (iUserId < 0)
                {
                    var errCode = coreInfrastructure.NetDvrGetLastError();
                    message = "NET_DVR_Login_V40 failed, error code= " + errCode;
                    coreInfrastructure.NetDvrCleanUp();
                    return null;
                }

                var devTime = new CHCNetSDK.NET_DVR_TIME();
                var dwSize = (int)Marshal.SizeOf(devTime);
                var ptrDevTime = Marshal.AllocHGlobal(dwSize);
                Marshal.StructureToPtr(devTime, ptrDevTime, true);
                uint dwReturn = 0;
                var res = CHCNetSDK.NET_DVR_GetDVRConfig(iUserId, CHCNetSDK.NET_DVR_GET_TIMECFG, 0, ptrDevTime, (uint)dwSize, ref dwReturn);
                devTime = (CHCNetSDK.NET_DVR_TIME)Marshal.PtrToStructure(ptrDevTime, typeof(CHCNetSDK.NET_DVR_TIME));

                DateTime? deviceDateTime = null;

                if (res)
                {
                    deviceDateTime= new DateTime((int)devTime.dwYear, (int)devTime.dwMonth, (int)devTime.dwDay, (int)devTime.dwHour, (int)devTime.dwMinute, (int)devTime.dwSecond);
                }
                Marshal.FreeHGlobal(ptrDevTime);

                LoginOutAndClearUp(iUserId);

                return deviceDateTime;
            }
            catch (Exception ex)
            {
                message = ex.Message;
                return null;
            }
        }

        /// <summary>
        /// 设置设备时间
        /// </summary>
        /// <param name="errorCode"></param>
        /// <param name="message"></param>
        /// <param name="deviceIp"></param>
        /// <param name="devicePort"></param>
        /// <param name="userName"></param>
        /// <param name="password"></param>
        /// <returns></returns>
        [HandleProcessCorruptedStateExceptions]
        public bool TimeSet(
            out int errorCode,
            out string message,
            DateTime newTime,
            string deviceIp,
            int devicePort,
            string userName = "admin",
            string password = "")
        {
            message = string.Empty;
            errorCode = -100;

            try
            {
                //初始化
                coreInfrastructure.NetDvrInit();

                //登录
                var iUserId = loginManage.LoginDevice(deviceIp, devicePort, userName, password, out errorCode);

                if (iUserId < 0)
                {
                    var errCode = coreInfrastructure.NetDvrGetLastError();
                    message = "NET_DVR_Login_V40 failed, error code= " + errCode;
                    coreInfrastructure.NetDvrCleanUp();
                    return false;
                }

                var curTime = new CHCNetSDK.NET_DVR_TIME
                {
                    dwYear = (uint) newTime.Year,
                    dwMonth = (uint) newTime.Month,
                    dwDay = (uint) newTime.Day,
                    dwHour = (uint) newTime.Hour,
                    dwMinute = (uint) newTime.Minute,
                    dwSecond = (uint) newTime.Second
                };

                var dwSize = (int)Marshal.SizeOf(curTime);
                var ptrCurTime = Marshal.AllocHGlobal(dwSize);
                Marshal.StructureToPtr(curTime, ptrCurTime, true);
                var res = CHCNetSDK.NET_DVR_SetDVRConfig(iUserId, CHCNetSDK.NET_DVR_SET_TIMECFG, 0, ptrCurTime, (uint)dwSize);
            
                Marshal.FreeHGlobal(ptrCurTime);

                if (!res)
                {
                    errorCode = (int) coreInfrastructure.NetDvrGetLastError();
                }
                
                LoginOutAndClearUp(iUserId);

                return res;
            }
            catch (Exception ex)
            {
                message = ex.Message;
                return false;
            }
        }


        /// <summary>
        /// 注销用户释放资源
        /// </summary>
        /// <param name="iUserId"></param>
        private void LoginOutAndClearUp(int iUserId)
        {
            //注销用户
            coreInfrastructure.NetDvrLogout(iUserId);
            //释放 SDK 资源
            coreInfrastructure.NetDvrCleanUp();
        }
    }
}
